// 客户端发送的数据与服务器端接收并发送的数据一致
#pragma once
#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
#include "InetAddr.hpp"
class UdpServer
{
public:
    UdpServer(/*const string ip, */ uint16_t port) // 需要传入端口号
        : _sockfd(-1), _port(port), _ip("0.0.0.0"), _isrunning(false)
    {
    }
    ~UdpServer() {}
    // 初始化服务器
    void InitServer()
    {
        // UDP初始化工作：创建套接字并绑定套接字与网络信息
        // 创建udp socket套接字
        _sockfd = socket(AF_INET /*网络套接字*/, SOCK_DGRAM /*支持数据报*/, 0 /*UDP*/);
        if (_sockfd < 0)
        {
            cout << "创建套接字失败" << endl;
            exit(-1);
        }
        else
        {
            cout << "创建套接字成功，套接字：" << _sockfd << endl;
        }
        // 绑定套接字和网络信息(ip地址和端口号)
        struct sockaddr_in local;      // 填写网络信息
        bzero(&local, sizeof(local));  // 清空struct sockaddr_in结构体开辟的空间
        local.sin_family = AF_INET;    // 填写通信类型(网络/本地)
        local.sin_port = htons(_port); // 端口号-主机序列转换网络序列
        // 将点分十进制ip地址转换为4字节ip地址，再将4字节ip地址转换从本地序列为网络序列
        // local.sin_addr.s_addr = inet_addr(_ip.c_str());
        local.sin_addr.s_addr = htonl(INADDR_ANY);
        int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            cout << "绑定套接字与网络信息失败" << endl;
            exit(-1);
        }
        else
        {
            cout << "绑定套接字与网络信息成功" << endl;
        }
    }
    // 启动服务器
    void Start()
    {
        // 服务器一直运行
        _isrunning = true;
        while (true)
        {
            // 接收信息(读取)
            char buffer[128]; // 信息缓冲区
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd, &buffer, sizeof(buffer) - 1, 0, (sockaddr *)&peer, &len);
            // 返回读取字符串长度个数
            if (n > 0)
            {
                InetAddr addr(peer);
                buffer[n] = '\0';
                printf("[ip:%s][port:%d][date:%s]\n", addr.Ip().c_str(), addr.Port(), buffer);
                // 发送信息(发送)
                sendto(_sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&peer, len);
            }
        }
        _isrunning = false;
    }

private:
    int _sockfd;
    string _ip;
    uint16_t _port;
    bool _isrunning;
};